// Copyright (c) 2011 Blue Onion Software, All rights reserved
using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.Linq;
using System.Web;

namespace BlueOnionSoftware.Bloget
{
    // Original source:
    // http://www.madskristensen.dk/blog/PermaLink,guid,60533e14-789d-41a1-92d2-43efddce7d8e.aspx

    public sealed class HttpCompressionModule : IHttpModule
    {
        private const string Gzip = "gzip";
        private const string Deflate = "deflate";
        private static readonly string[] _exceptions = {"=RSS", "=RPC", ".AXD"};

        void IHttpModule.Init(HttpApplication context)
        {
            context.BeginRequest += BeginRequest;
        }

        private static void BeginRequest(object sender, EventArgs e)
        {
            if (RequestContains(_exceptions) == false)
            {
                var app = sender as HttpApplication;

                if (app != null)
                {
                    if (EncodingAccepted(Deflate))
                    {
                        app.Response.Filter = new DeflateStream(app.Response.Filter, CompressionMode.Compress);
                        SetEncoding(Deflate);
                    }

                    else if (EncodingAccepted(Gzip))
                    {
                        app.Response.Filter = new GZipStream(app.Response.Filter, CompressionMode.Compress);
                        SetEncoding(Gzip);
                    }
                }
            }
        }

        private static bool RequestContains(IEnumerable<string> values)
        {
            var request = HttpContext.Current.Request.Url.AbsoluteUri.ToUpperInvariant();
            return values.Any(value => request.Contains(value));
        }

        private static bool EncodingAccepted(string encoding)
        {
            var acceptEncoding = HttpContext.Current.Request.Headers["Accept-encoding"] ?? string.Empty;
            return acceptEncoding.Contains(encoding);
        }

        private static void SetEncoding(string encoding)
        {
            HttpContext.Current.Response.AppendHeader("Content-encoding", encoding);
        }

        void IHttpModule.Dispose()
        {
        }
    }
}